home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / tsipp / tsipp.lha / tsipp3.0a / src / tSippRLE.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-02  |  24.2 KB  |  735 lines

  1. /*
  2.  *=============================================================================
  3.  *                                  tSippRLE.c
  4.  *-----------------------------------------------------------------------------
  5.  * Tcl commands to render to Utah Raster Toolkit RLE files.
  6.  *-----------------------------------------------------------------------------
  7.  * Copyright 1992 Mark Diekhans
  8.  * Permission to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted, provided
  10.  * that the above copyright notice appear in all copies.  Mark Diekhans makes
  11.  * no representations about the suitability of this software for any purpose.
  12.  * It is provided "as is" without express or implied warranty.
  13.  *-----------------------------------------------------------------------------
  14.  * $Id: tSippRLE.c,v 2.0 1992/11/02 03:56:33 markd Rel $
  15.  *=============================================================================
  16.  */
  17.  
  18. #include "tSippInt.h"
  19. #include "sipp_pixmap.h"
  20. #include "sipp_bitmap.h"
  21.  
  22. #ifndef TSIPP_NO_RLE
  23.  
  24. #include "rle.h"
  25.  
  26. /*
  27.  * Type used to hold a file handle "fileNNN".
  28.  */
  29. typedef char fileHandle_t [10];
  30.  
  31. /*
  32.  * RLE file table entry.
  33.  */
  34. typedef struct {
  35.     fileHandle_t handle;
  36.     rle_hdr      rleHeader;
  37. } rleFile_t, *rleFile_pt;
  38.  
  39. /*
  40.  * Client-data for pixel setting call back used to hold a single row of data.
  41.  * The data will be outputed when the last pixel is written.
  42.  */
  43. typedef struct {
  44.     rle_hdr    *rleHdrPtr;
  45.     rle_pixel **rowPtr;
  46. } renderData_t, *renderData_pt;
  47.  
  48. /*
  49.  * Internal prototypes.
  50.  */
  51. static rleFile_pt
  52. RLEHandleToPtr _ANSI_ARGS_((tSippGlob_pt    tSippGlobPtr,
  53.                             char           *handle));
  54.  
  55. static rleFile_pt
  56. RLECommentCmdSetup _ANSI_ARGS_((tSippGlob_pt    tSippGlobPtr,
  57.                                 char           *handle,
  58.                                 char           *name));
  59.  
  60. static void
  61. RLEPixelRender _ANSI_ARGS_((renderData_pt  renderDataPtr,
  62.                             int            x,
  63.                             int            y,
  64.                             unsigned char  red,
  65.                             unsigned char  green,
  66.                             unsigned char  blue));
  67.  
  68. static void
  69. RLERenderImage _ANSI_ARGS_((tSippGlob_pt         tSippGlobPtr,
  70.                             rleFile_pt           rleFilePtr,
  71.                             tSippRenderParms_pt  renderParmsPtr));
  72.  
  73. static void
  74. RLEOutputBitMap _ANSI_ARGS_((tSippGlob_pt   tSippGlobPtr,
  75.                              rleFile_pt     rleFilePtr, 
  76.                              Sipp_bitmap   *bitMapPtr));
  77.  
  78. static void
  79. RLEDrawImage _ANSI_ARGS_((tSippGlob_pt         tSippGlobPtr,
  80.                           rleFile_pt           rleFilePtr,
  81.                           tSippRenderParms_pt  renderParmsPtr));
  82.  
  83. /*=============================================================================
  84.  * RLEHandleToPtr --
  85.  *   Utility procedure to convert a RLE file handle to a RLE header pointer.
  86.  * Parameters:
  87.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  88.  *   o handle (I) - A RLE handle.
  89.  * Returns:
  90.  *   A pointer to the RLE file entry., or NULL if an error occured.
  91.  *-----------------------------------------------------------------------------
  92.  */
  93. static rleFile_pt
  94. RLEHandleToPtr (tSippGlobPtr, handle)
  95.     tSippGlob_pt    tSippGlobPtr;
  96.     char           *handle;
  97. {
  98.     rleFile_pt  rleFilePtr;
  99.  
  100.     rleFilePtr = (rleFile_pt)
  101.         Tcl_HandleXlate (tSippGlobPtr->interp,
  102.                          tSippGlobPtr->rleTblPtr, handle);
  103.     if (rleFilePtr == NULL)
  104.         return NULL;
  105.     return rleFilePtr;
  106.  
  107. } /* RLEHandleToPtr */
  108.  
  109. /*=============================================================================
  110.  * SippRLEOpen --
  111.  *   Implements the command:
  112.  *     SippRLEOpen filename mode
  113.  * Note:
  114.  *   This procedure has standard Tcl command calling sematics.  ClientData
  115.  * contains a pointer to the Tcl SIPP global structure.* We cheat by calling
  116.  * the Tcl "open" command executor to actually do the open, that way we get the
  117.  * full semantics of the open command.
  118.  *-----------------------------------------------------------------------------
  119.  */
  120. static int
  121. SippRLEOpen (clientData, interp, argc, argv)
  122.     char       *clientData;
  123.     Tcl_Interp *interp;
  124.     int         argc;
  125.     char      **argv;
  126. {
  127.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  128.     fileHandle_t    fileHandle;
  129.     rleFile_pt      rleFilePtr;
  130.     OpenFile       *filePtr;
  131.  
  132.     if (argc != 3) {
  133.         Tcl_AppendResult (interp, "wrong # args: ", argv [0],
  134.                           " filename mode", (char *) NULL);
  135.         return TCL_ERROR;
  136.     }
  137.     /*
  138.      * Validate mode (we restrict it since reading of RLE files in not
  139.      * supported).
  140.      */
  141.     if (argv [2][1] != '\0')
  142.         goto invalidMode;
  143.     if (!((argv [2][0] == 'w') || (argv [2][0] == 'a')))
  144.         goto invalidMode;
  145.  
  146.     /*
  147.      * Use the open command to actually open the file.  If it succeeds, save
  148.      * the handle, which will latter be stored in the RLE file table entry.
  149.      */
  150.  
  151.     if (Tcl_OpenCmd (NULL, interp, argc, argv) != TCL_OK)
  152.         return TCL_ERROR;
  153.     strcpy (fileHandle, interp->result);
  154.     Tcl_ResetResult (interp);
  155.  
  156.     if (TclGetOpenFile (interp, fileHandle, &filePtr) != TCL_OK)
  157.          return TCL_ERROR;
  158.  
  159.     /*
  160.      * Allocate and initialize the RLE header struct, defaulting all fields.
  161.      */
  162.     rleFilePtr = (rleFile_pt) Tcl_HandleAlloc (tSippGlobPtr->rleTblPtr,
  163.                                                interp->result);
  164.     rleFilePtr->rleHeader = rle_dflt_hdr;
  165.     rleFilePtr->rleHeader.rle_file = filePtr->f;
  166.     strcpy (rleFilePtr->handle, fileHandle);
  167.  
  168.     return TCL_OK;
  169.  
  170. invalidMode:
  171.     Tcl_AppendResult (interp, "invalid mode \"", argv [2], 
  172.                       "\" expected one of: \"w\" or \"a\"", (char *) NULL);
  173.     return TCL_ERROR;
  174.  
  175. } /* SippRLEOpen */
  176.  
  177. /*=============================================================================
  178.  * SippRLEClose --
  179.  *   Implements the command:
  180.  *     SippRLEClose rlehandle
  181.  * Note:
  182.  *   This procedure has standard Tcl command calling sematics.  ClientData
  183.  * contains a pointer to the Tcl SIPP global structure.
  184.  *-----------------------------------------------------------------------------
  185.  */
  186. static int
  187. SippRLEClose (clientData, interp, argc, argv)
  188.     char       *clientData;
  189.     Tcl_Interp *interp;
  190.     int         argc;
  191.     char      **argv;
  192. {
  193.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  194.     rleFile_pt      rleFilePtr;
  195.     int             result;
  196.     char           *closeArgv [2];
  197.  
  198.     if (argc != 2) {
  199.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  200.                           " rlehandle", (char *) NULL);
  201.         return TCL_ERROR;
  202.     }
  203.  
  204.     rleFilePtr = RLEHandleToPtr (tSippGlobPtr, argv [1]);
  205.     if (rleFilePtr == NULL)
  206.         return TCL_ERROR;
  207.  
  208.     closeArgv [0] = argv [0];
  209.     closeArgv [1] = rleFilePtr->handle;
  210.  
  211.     result = Tcl_CloseCmd (NULL, interp, 2, closeArgv);
  212.     
  213.     Tcl_HandleFree (tSippGlobPtr->rleTblPtr, rleFilePtr);
  214.     return result;
  215.  
  216. } /* SippRLEClose */
  217.  
  218. /*=============================================================================
  219.  * RLECommentCmdSetup --
  220.  *   Utility procedure to set up for one of the comments commands.  If converts
  221.  * the rlehandle and validates the comment name.
  222.  * Parameters:
  223.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  224.  *   o handle (I) - A RLE handle.
  225.  *   o name (I) - The name of the commane.  If NULL, then it is not validated
  226.  * Returns:
  227.  *   A pointer to the RLE file entry, or NULL if an error occured.  Errors
  228.  * returned in tSippGlobPtr->interp->result.
  229.  *-----------------------------------------------------------------------------
  230.  */
  231. static rleFile_pt
  232. RLECommentCmdSetup (tSippGlobPtr, handle, name)
  233.     tSippGlob_pt    tSippGlobPtr;
  234.     char           *handle;
  235.     char           *name;
  236. {
  237.     rleFile_pt  rleFilePtr;
  238.  
  239.     rleFilePtr = RLEHandleToPtr (tSippGlobPtr, handle);
  240.     if (rleFilePtr == NULL)
  241.         return NULL;
  242.  
  243.     if ((name != NULL)  && (strpbrk (name, " \f\n\r\t\v=") != NULL)) {
  244.         Tcl_AppendResult (tSippGlobPtr->interp, "name may not contain the ",
  245.                           "`=' or whitespace characters", (char *) NULL);
  246.         return NULL;
  247.     }
  248.     return rleFilePtr;
  249.  
  250. } /* RLECommentCmdSetup */
  251.  
  252. /*=============================================================================
  253.  * SippRLEPutCom --
  254.  *   Implements the command:
  255.  *     SippRLEPutCom rlehandle name [value]
  256.  * Note:
  257.  *   This procedure has standard Tcl command calling sematics.  ClientData
  258.  * contains a pointer to the Tcl SIPP global structure.
  259.  *-----------------------------------------------------------------------------
  260.  */
  261. static int
  262. SippRLEPutCom (clientData, interp, argc, argv)
  263.     char       *clientData;
  264.     Tcl_Interp *interp;
  265.     int         argc;
  266.     char      **argv;
  267. {
  268.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  269.     rleFile_pt      rleFilePtr;
  270.     int             comStrLen;
  271.     char           *comStr, *oldComStr;
  272.  
  273.     if ((argc < 3) || (argc > 4)) {
  274.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  275.                           " rlehandle name [value]", (char *) NULL);
  276.         return TCL_ERROR;
  277.     }
  278.     rleFilePtr = RLECommentCmdSetup (tSippGlobPtr, argv [1], argv [2]);
  279.     if (rleFilePtr == NULL)
  280.         return TCL_ERROR;
  281.  
  282.     if (argc == 3) 
  283.         comStrLen = strlen (argv [2]) + 1;
  284.     else
  285.         comStrLen = strlen (argv [2]) + strlen (argv [3]) + 2;
  286.  
  287.     comStr = malloc (comStrLen);
  288.     strcpy (comStr, argv [2]);
  289.     if (argc > 3 ) {
  290.         strcat (comStr, "=");
  291.         strcat (comStr, argv [3]);
  292.     }
  293.     oldComStr = rle_putcom (comStr, &rleFilePtr->rleHeader);
  294.     if (oldComStr != NULL)
  295.         free (oldComStr);
  296.  
  297.     return TCL_OK;
  298.  
  299. } /* SippRLEPutCom */
  300.  
  301. /*=============================================================================
  302.  * SippRLEGetCom --
  303.  *   Implements the command:
  304.  *     SippRLEGetCom rlehandle name [retvar | {}]
  305.  * Note:
  306.  *   This procedure has standard Tcl command calling sematics.  ClientData
  307.  * contains a pointer to the Tcl SIPP global structure.
  308.  *-----------------------------------------------------------------------------
  309.  */
  310. static int
  311. SippRLEGetCom (clientData, interp, argc, argv)
  312.     char       *clientData;
  313.     Tcl_Interp *interp;
  314.     int         argc;
  315.     char      **argv;
  316. {
  317.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  318.     rleFile_pt      rleFilePtr;
  319.     char           *comStr;
  320.  
  321.     if ((argc < 3) || (argc > 4)) {
  322.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  323.                           " rlehandle name [retvar | {}]", (char *) NULL);
  324.         return TCL_ERROR;
  325.     }
  326.  
  327.     rleFilePtr = RLECommentCmdSetup (tSippGlobPtr, argv [1], argv [2]);
  328.     if (rleFilePtr == NULL)
  329.         return TCL_ERROR;
  330.  
  331.     comStr = rle_getcom (argv [2], &rleFilePtr->rleHeader);
  332.  
  333.     /*
  334.      * If comment was not found, either return false or leave result an empty
  335.      * string.  If its was found, either return it in the variable or as the
  336.      * command result.
  337.      */
  338.     if (comStr == NULL) {
  339.         if (argc == 4)
  340.             interp->result = "0";
  341.     } else {
  342.         if (argc == 4) {
  343.             if (argv [3][0] != '\0') {
  344.                 if (Tcl_SetVar (interp, argv [3], comStr, 
  345.                                 TCL_LEAVE_ERR_MSG) == NULL)
  346.                     return TCL_ERROR;
  347.             }
  348.             interp->result = "1";
  349.         } else {
  350.             Tcl_SetResult (interp, comStr, TCL_STATIC);
  351.         }
  352.     }
  353.     return TCL_OK;
  354.  
  355. } /* SippRLEGetCom */
  356.  
  357. /*=============================================================================
  358.  * SippRLEDelCom --
  359.  *   Implements the command:
  360.  *     SippRLEDelCom rlehandle name
  361.  * Note:
  362.  *   This procedure has standard Tcl command calling sematics.  ClientData
  363.  * contains a pointer to the Tcl SIPP global structure.
  364.  *-----------------------------------------------------------------------------
  365.  */
  366. static int
  367. SippRLEDelCom (clientData, interp, argc, argv)
  368.     char       *clientData;
  369.     Tcl_Interp *interp;
  370.     int         argc;
  371.     char      **argv;
  372. {
  373.     tSippGlob_pt    tSippGlobPtr = (tSippGlob_pt) clientData;
  374.     rleFile_pt      rleFilePtr;
  375.     char           *comStr;
  376.  
  377.     if (argc != 3) {
  378.         Tcl_AppendResult (interp, "wrong # args: ", argv [0], 
  379.                           " rlehandle name", (char *) NULL);
  380.         return TCL_ERROR;
  381.     }
  382.     rleFilePtr = RLECommentCmdSetup (tSippGlobPtr, argv [1], argv [2]);
  383.     if (rleFilePtr == NULL)
  384.         return TCL_ERROR;
  385.  
  386.     comStr = rle_delcom (argv [2], &rleFilePtr->rleHeader);
  387.     if (comStr != NULL)
  388.         free (comStr);
  389.  
  390.     return TCL_OK;
  391.  
  392. } /* SippRLEDelCom */
  393.  
  394. /*=============================================================================
  395.  * RLEPixelRender --
  396.  *   Pixel rendering call back procedure.  SIPP doesn't have the concept of 
  397.  * background and always involkes the call back for every pixel.
  398.  *
  399.  * Parameters:
  400.  *   o renderDataPtr (I) - A pointer to the clientdata, It contains a buffer
  401.  *     with the row of data currently being rendered.
  402.  *   o x, y (I) - The pixel coordinate.
  403.  *   o red, green, blue - (I) - The color values for the pixel.
  404.  *-----------------------------------------------------------------------------
  405.  */
  406. static void
  407. RLEPixelRender (renderDataPtr, x, y, red, green, blue)
  408.     renderData_pt  renderDataPtr;
  409.     int            x;
  410.     int            y;
  411.     unsigned char  red;
  412.     unsigned char  green;
  413.     unsigned char  blue;
  414. {
  415.  
  416.     renderDataPtr->rowPtr [RLE_RED] [x]   = red;
  417.     renderDataPtr->rowPtr [RLE_GREEN] [x] = green;
  418.     renderDataPtr->rowPtr [RLE_BLUE] [x]  = blue;
  419.     
  420.     if (x >= renderDataPtr->rleHdrPtr->xmax)
  421.         rle_putrow (renderDataPtr->rowPtr, renderDataPtr->rleHdrPtr->xmax,
  422.                     renderDataPtr->rleHdrPtr);
  423.  
  424. } /* RLEPixelRender */
  425.  
  426. /*=============================================================================
  427.  * RLERenderImage --
  428.  *   Render an image to a RLE file.  The RLE file should have had all initial
  429.  * setup performed.
  430.  *
  431.  * Parameters:
  432.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  433.  *   o rleFilePtr (I) - A pointer to the RLE file entry.
  434.  *   o renderParmsPtr (I) - The rendering parameters parsed from the command
  435.  *     line.
  436.  *-----------------------------------------------------------------------------
  437.  */
  438. static void
  439. RLERenderImage (tSippGlobPtr, rleFilePtr, renderParmsPtr)
  440.     tSippGlob_pt         tSippGlobPtr;
  441.     rleFile_pt           rleFilePtr;
  442.     tSippRenderParms_pt  renderParmsPtr;
  443. {
  444.     renderData_t renderData;
  445.  
  446.     /*
  447.      * Set up the client-data with one scan line worth of buffer.
  448.      */
  449.     renderData.rleHdrPtr = &rleFilePtr->rleHeader;
  450.     rle_row_alloc (&rleFilePtr->rleHeader, &renderData.rowPtr);
  451.  
  452.     if (renderParmsPtr->interlaced)
  453.         render_field_func (renderParmsPtr->xSize,
  454.                            renderParmsPtr->ySize,
  455.                            RLEPixelRender,
  456.                            &renderData, 
  457.                            renderParmsPtr->mode,
  458.                            renderParmsPtr->overSampling,
  459.                            renderParmsPtr->field);
  460.     else
  461.         render_image_func (renderParmsPtr->xSize,
  462.                            renderParmsPtr->ySize,
  463.                            RLEPixelRender,
  464.                            &renderData, 
  465.                            renderParmsPtr->mode,
  466.                            renderParmsPtr->overSampling);
  467.  
  468.     rle_row_free (&rleFilePtr->rleHeader, renderData.rowPtr);
  469.  
  470. } /* RLERenderImage */
  471.  
  472. /*=============================================================================
  473.  * RLEOutputBitMap --
  474.  *   Output a SIPP bit map to a RLE file.  The scan lines are done in reverse
  475.  * to account for the difference in the idea of which end is up between SIPP
  476.  * and RLE.
  477.  *
  478.  * Parameters:
  479.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  480.  *   o rleFilePtr (I) - Pointer to the RLE file entry, should be all set up
  481.  *     for rle_row_put.
  482.  *   o bitMapPtr (I) - Pointer to the SIPP bit map structure.
  483.  *-----------------------------------------------------------------------------
  484.  */
  485. static void
  486. RLEOutputBitMap (tSippGlobPtr, rleFilePtr, bitMapPtr)
  487.     tSippGlob_pt   tSippGlobPtr;
  488.     rleFile_pt     rleFilePtr;
  489.     Sipp_bitmap   *bitMapPtr;
  490. {
  491.     rle_pixel **rowPtr;
  492.     int         x, y;
  493.     unsigned    bit;
  494.     u_char     *pixRowPtr;
  495.     int         lineColor [3], backgroundColor [3];
  496.  
  497.     lineColor [RLE_RED]   = tSippGlobPtr->lineColor.red * 255;
  498.     lineColor [RLE_GREEN] = tSippGlobPtr->lineColor.grn * 255;
  499.     lineColor [RLE_BLUE]  = tSippGlobPtr->lineColor.blu * 255;
  500.  
  501.     backgroundColor [RLE_RED]   = tSippGlobPtr->backgroundColor.red * 255;
  502.     backgroundColor [RLE_GREEN] = tSippGlobPtr->backgroundColor.grn * 255;
  503.     backgroundColor [RLE_BLUE]  = tSippGlobPtr->backgroundColor.blu * 255;
  504.  
  505.     rle_row_alloc (&rleFilePtr->rleHeader, &rowPtr);
  506.  
  507.     for (y = rleFilePtr->rleHeader.ymax - 1; y >= 0 ; y--) {
  508.         pixRowPtr = &bitMapPtr->buffer [y * bitMapPtr->width_bytes];
  509.  
  510.         for (x = 0; x < rleFilePtr->rleHeader.xmax; x++) {
  511.             bit = (pixRowPtr [x >> 3] >> (7-(x & 7))) & 1;
  512.             if (bit) {
  513.                 rowPtr [RLE_RED] [x]   = lineColor [RLE_RED];
  514.                 rowPtr [RLE_GREEN] [x] = lineColor [RLE_GREEN];
  515.                 rowPtr [RLE_BLUE] [x]  = lineColor [RLE_BLUE];
  516.             } else {
  517.                 rowPtr [RLE_RED] [x]   = backgroundColor [RLE_RED];
  518.                 rowPtr [RLE_GREEN] [x] = backgroundColor [RLE_GREEN];
  519.                 rowPtr [RLE_BLUE] [x]  = backgroundColor [RLE_BLUE];
  520.             }
  521.         }
  522.         rle_putrow (rowPtr, rleFilePtr->rleHeader.xmax,
  523.                     &rleFilePtr->rleHeader);
  524.     }
  525.  
  526.     rle_row_free (&rleFilePtr->rleHeader, rowPtr);
  527.  
  528. } /* RLEOutputBitMap */
  529.  
  530. /*=============================================================================
  531.  * RLEDrawImage --
  532.  *   Render a line image to a RLE file.  The RLE file should have had all
  533.  * initial setup performed.
  534.  *
  535.  * Parameters:
  536.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  537.  *   o rleFilePtr (I) - A pointer to the RLE file entry.
  538.  *   o renderParmsPtr (I) - The rendering parameters parsed from the command
  539.  *     line.
  540.  *-----------------------------------------------------------------------------
  541.  */
  542. static void
  543. RLEDrawImage (tSippGlobPtr, rleFilePtr, renderParmsPtr)
  544.     tSippGlob_pt         tSippGlobPtr;
  545.     rleFile_pt           rleFilePtr;
  546.     tSippRenderParms_pt  renderParmsPtr;
  547. {
  548.     Sipp_bitmap  *bitMapPtr;
  549.  
  550.     /*
  551.      * Create bit map and use the standard SIPP call back to draw the lines.
  552.      */
  553.     bitMapPtr = sipp_bitmap_create (renderParmsPtr->xSize, 
  554.                                     renderParmsPtr->ySize);
  555.     render_image_func (renderParmsPtr->xSize,
  556.                        renderParmsPtr->ySize,
  557.                        sipp_bitmap_line,
  558.                        bitMapPtr,
  559.                        LINE, 0);
  560.  
  561.     RLEOutputBitMap (tSippGlobPtr, rleFilePtr, bitMapPtr);
  562.  
  563.     sipp_bitmap_destruct (bitMapPtr);
  564.  
  565. } /* RLEDrawImage */
  566.  
  567. /*=============================================================================
  568.  * SippRLERender --
  569.  *   Implements the command:
  570.  *     SippRLERender rlehandle xsize ysize [mode] [oversample]
  571.  * Note:
  572.  *   This procedure has standard Tcl command calling sematics.  ClientData
  573.  * contains a pointer to the Tcl SIPP global structure.
  574.  *-----------------------------------------------------------------------------
  575.  */
  576. static int
  577. SippRLERender (clientData, interp, argc, argv)
  578.     char       *clientData;
  579.     Tcl_Interp *interp;
  580.     int         argc;
  581.     char      **argv;
  582. {
  583.     tSippGlob_pt         tSippGlobPtr = (tSippGlob_pt) clientData;
  584.     rleFile_pt           rleFilePtr;
  585.     int                  background [3];
  586.     tSippRenderParms_t   renderParms;
  587.     char                *versionStr, *oldVersionStr;
  588.  
  589.     if (!TSippParseRenderParms (tSippGlobPtr, argc, argv, "rlehandle",
  590.                                 &renderParms))
  591.         return TCL_ERROR;
  592.  
  593.     rleFilePtr = RLEHandleToPtr (tSippGlobPtr, renderParms.fileHandle);
  594.     if (rleFilePtr == NULL)
  595.         return TCL_ERROR;
  596.  
  597.     /*
  598.      * RLE expects scan lines in the reverse order of standard SIPP algorithm.
  599.      */
  600.     sipp_render_direction (TRUE);
  601.  
  602.     /*
  603.      * Set up the RLE header for a 24 bit image and write it.
  604.      */
  605.     rleFilePtr->rleHeader.ncolors = 3;  /* Red, Green and Blue */
  606.     rleFilePtr->rleHeader.xmin = 0;
  607.     rleFilePtr->rleHeader.xmax = renderParms.xSize - 1;
  608.     rleFilePtr->rleHeader.ymin = 0;
  609.     rleFilePtr->rleHeader.ymax = renderParms.ySize - 1;
  610.  
  611.     RLE_SET_BIT (rleFilePtr->rleHeader, RLE_RED);
  612.     RLE_SET_BIT (rleFilePtr->rleHeader, RLE_GREEN);
  613.     RLE_SET_BIT (rleFilePtr->rleHeader, RLE_BLUE);
  614.  
  615.     background [RLE_RED]   = tSippGlobPtr->backgroundColor.red;
  616.     background [RLE_GREEN] = tSippGlobPtr->backgroundColor.grn;
  617.     background [RLE_BLUE]  = tSippGlobPtr->backgroundColor.blu;
  618.  
  619.     rleFilePtr->rleHeader.bg_color = background;
  620.     rleFilePtr->rleHeader.background = 2;        /* Use background color */
  621.  
  622.     /*
  623.      * Add Tcl-SIPP version command and command history to the header.
  624.      */
  625.  
  626.     versionStr = malloc (strlen (TSIPP_VERSION) + 15);
  627.     strcpy (versionStr, "TSIPP_VERSION=");
  628.     strcat (versionStr, TSIPP_VERSION);
  629.     oldVersionStr = rle_putcom (versionStr, &rleFilePtr->rleHeader);
  630.     if (oldVersionStr != NULL)
  631.         free (oldVersionStr);
  632.  
  633.     rle_addhist (argv, (rle_hdr *) 0, &rleFilePtr->rleHeader);
  634.  
  635.     rle_put_setup (&rleFilePtr->rleHeader);
  636.  
  637.     if (renderParms.mode == LINE)
  638.         RLEDrawImage (tSippGlobPtr, rleFilePtr, &renderParms);
  639.     else
  640.         RLERenderImage (tSippGlobPtr, rleFilePtr, &renderParms);
  641.  
  642.     rle_puteof (&rleFilePtr->rleHeader);
  643.  
  644.     return TCL_OK;
  645.  
  646. } /* SippRLERender */
  647.  
  648. /*=============================================================================
  649.  * TSippRLEInit --
  650.  *   Initialized the Utah Raster Toolkit RLE commands and the RLE file
  651.  *   table.
  652.  *
  653.  * Parameters:
  654.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  655.  *-----------------------------------------------------------------------------
  656.  */
  657. void
  658. TSippRLEInit (tSippGlobPtr)
  659.     tSippGlob_pt  tSippGlobPtr;
  660. {
  661.     static tSippTclCmdTbl_t cmdTable [] = {
  662.         {"SippRLEOpen",       SippRLEOpen},
  663.         {"SippRLEClose",      SippRLEClose},
  664.         {"SippRLEPutCom",     SippRLEPutCom},
  665.         {"SippRLEGetCom",     SippRLEGetCom},
  666.         {"SippRLEDelCom",     SippRLEDelCom},
  667.         {"SippRLERender",     SippRLERender},
  668.         {NULL,                NULL}
  669.     };
  670.  
  671.     tSippGlobPtr->rleTblPtr =
  672.         Tcl_HandleTblInit ("rlefile", sizeof (rleFile_t), 4);
  673.  
  674.     TSippInitCmds (tSippGlobPtr, cmdTable);
  675.  
  676. } /* TSippRLEInit */
  677.  
  678. #else /* TSIPP_NO_RLE */
  679.  
  680. /*=============================================================================
  681.  * SippRLEIsNotHere --
  682.  *   Implements the a command that returns a error indicates that the Utah
  683.  * Raster Toolkit is not available.  If this module is compiled with
  684.  * TSIPP_NO_RLE defined, all RLE commands are bound to this command.
  685.  *
  686.  * Note:
  687.  *   This procedure has standard Tcl command calling sematics.  ClientData
  688.  * contains a pointer to the Tcl SIPP global structure.
  689.  *-----------------------------------------------------------------------------
  690.  */
  691. static int
  692. SippRLEIsNotHere (clientData, interp, argc, argv)
  693.     char       *clientData;
  694.     Tcl_Interp *interp;
  695.     int         argc;
  696.     char      **argv;
  697. {
  698.     Tcl_AppendResult (interp, "The Utah Raster Toolkit RLE library has not ",
  699.                       "been linked into\n", "this program. ", argv [0],
  700.                       " is not available", (char *) NULL);
  701.     return TCL_ERROR;
  702.  
  703. } /* SippRLEIsNotHere */
  704.  
  705. /*=============================================================================
  706.  * TSippRLEInit --
  707.  *   Initialization when the Utah Raster Toolkit is not available.  Bind all
  708.  *   commands to a routine that returns an error.
  709.  *
  710.  * Parameters:
  711.  *   o tSippGlobPtr (I) - A pointer to the Tcl SIPP global structure.
  712.  *-----------------------------------------------------------------------------
  713.  */
  714. void
  715. TSippRLEInit (tSippGlobPtr)
  716.     tSippGlob_pt  tSippGlobPtr;
  717. {
  718.     static tSippTclCmdTbl_t cmdTable [] = {
  719.         {"SippRLEOpen",       SippRLEIsNotHere},
  720.         {"SippRLEClose",      SippRLEIsNotHere},
  721.         {"SippRLEPutCom",     SippRLEIsNotHere},
  722.         {"SippRLEGetCom",     SippRLEIsNotHere},
  723.         {"SippRLEDelCom",     SippRLEIsNotHere},
  724.         {"SippRLERender",     SippRLEIsNotHere},
  725.         {NULL,                NULL}
  726.     };
  727.  
  728.     tSippGlobPtr->rleTblPtr = NULL;
  729.  
  730.     TSippInitCmds (tSippGlobPtr, cmdTable);
  731.  
  732. } /* TSippRLEInit */
  733.  
  734. #endif /* TSIPP_NO_RLE */
  735.